﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using System.Xml;
using System.Threading;
using System.Xml.Linq;
using System.IO.IsolatedStorage;
using anael.Data.BO;
using anael.neuralNetwork;

public class CalculRN
{
    public int[] nombreNeuroneParCouche = new int[3];
    public double alpha;

    public Reseau res = new Reseau();

    public CalculRN(double _alpha, int _nbrNeuroneCouche1, int _nbrNeuroneCouche2, int _nbrNeuroneCouche3)
    {
        alpha = _alpha;
        nombreNeuroneParCouche[0] = _nbrNeuroneCouche1;
        nombreNeuroneParCouche[1] = _nbrNeuroneCouche2;
        nombreNeuroneParCouche[2] = _nbrNeuroneCouche3; 
    }

    public Reseau calculRetropropagation(List<EntriesTarget> listEntriesTarget)
    {
        int size = nombreNeuroneParCouche.Length;

        //Instantiation du RN
        res = new Reseau(nombreNeuroneParCouche, alpha);

        Random r = new Random();
        int NbreAlea = 0;

        int iter = 200000;

        do
        {
            NbreAlea = r.Next(listEntriesTarget.Count);

            res.insertData(listEntriesTarget[NbreAlea].entries);

            for (int i = 1; i <= size - 1; i++)
            {
                res.loadNextLayer(i);
                res.getC(i).calculPotentielCouche();
            }

            //Retropropagation du Gradient
            for (int i = 1; i <= size - 1; i++)
            {
                if (i == 1)
                {
                    for (int j = 0; j <= ((nombreNeuroneParCouche[size - i]) - 1); j++)
                    {
                        Perceptron p = res.getC(size - 1).getPerceptron(j);
                        res.calculErreur(j, listEntriesTarget[NbreAlea].target[j]);
                        p.calculDeltaPoid();
                    }
                }
                else
                {
                    for (int j = 0; j <= ((nombreNeuroneParCouche[size - i]) - 1); j++)
                    {
                        Perceptron p = res.getC(size - i).getPerceptron(j);
                        res.calculErreur(j, size - i);
                        p.calculDeltaPoid();
                    }
                }
            }

            iter = iter - 1;

        } while (iter > 0);

        return res;
    }

    public List<Potential> calculActivite(EntriesTarget entriesTarget, Reseau res)
    {
        int size = nombreNeuroneParCouche.Length;
        List<Potential> rslt = new List<Potential>();

        //Présentation du motif a tester
        res.insertData(entriesTarget.entries);
        for (int i = 1; i <= size - 1; i++)
        {
            res.loadNextLayer(i);
            res.getC(i).calculPotentielCouche();
        }

        //Construction du tableau de resultat
        for (int i = 0; i <= nombreNeuroneParCouche[size - 1] - 1; i++)
        {
            Potential pot = new Potential() {ID = i, PotentialLevel = res.getC(size - 1).getPerceptron(i).getSortie };
            rslt.Add(pot); 
        }

        return rslt;
    }

    public List<Potential> calculActivite(double[] entries, Reseau res)
    {
        int size = nombreNeuroneParCouche.Length;
        List<Potential> rslt = new List<Potential>();

        //Présentation du motif a tester
        res.insertData(entries);
        for (int i = 1; i <= size - 1; i++)
        {
            res.loadNextLayer(i);
            res.getC(i).calculPotentielCouche();
        }

        //Construction du tableau de resultat
        for (int i = 0; i <= nombreNeuroneParCouche[size - 1] - 1; i++)
        {
            Potential pot = new Potential() { ID = i, PotentialLevel = res.getC(size - 1).getPerceptron(i).getSortie };
            rslt.Add(pot); 
        }

        return rslt;
    }
}